2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-9 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #include "../JuceLibraryCode/JuceHeader.h"
27 #include "GraphEditorPanel.h"
28 #include "InternalFilters.h"
29 #include "MainHostWindow.h"
32 //==============================================================================
34 static Array
<PluginWindow
*> activePluginWindows
;
36 PluginWindow::PluginWindow (Component
* const uiComp
,
37 AudioProcessorGraph::Node
* owner_
,
38 const bool isGeneric_
)
39 : DocumentWindow (uiComp
->getName(), Colours::lightblue
,
40 DocumentWindow::minimiseButton
| DocumentWindow::closeButton
),
42 isGeneric (isGeneric_
)
46 setContentOwned (uiComp
, true);
48 setTopLeftPosition (owner
->properties
.getWithDefault ("uiLastX", Random::getSystemRandom().nextInt (500)),
49 owner
->properties
.getWithDefault ("uiLastY", Random::getSystemRandom().nextInt (500)));
52 activePluginWindows
.add (this);
55 void PluginWindow::closeCurrentlyOpenWindowsFor (const uint32 nodeId
)
57 for (int i
= activePluginWindows
.size(); --i
>= 0;)
58 if (activePluginWindows
.getUnchecked(i
)->owner
->nodeId
== nodeId
)
59 delete activePluginWindows
.getUnchecked(i
);
62 void PluginWindow::closeAllCurrentlyOpenWindows()
64 for (int i
= activePluginWindows
.size(); --i
>= 0;)
65 delete activePluginWindows
.getUnchecked(i
);
68 PluginWindow
* PluginWindow::getWindowFor (AudioProcessorGraph::Node
* node
,
71 for (int i
= activePluginWindows
.size(); --i
>= 0;)
72 if (activePluginWindows
.getUnchecked(i
)->owner
== node
73 && activePluginWindows
.getUnchecked(i
)->isGeneric
== useGenericView
)
74 return activePluginWindows
.getUnchecked(i
);
76 AudioProcessorEditor
* ui
= nullptr;
80 ui
= node
->getProcessor()->createEditorIfNeeded();
83 useGenericView
= true;
88 ui
= new GenericAudioProcessorEditor (node
->getProcessor());
93 AudioPluginInstance
* const plugin
= dynamic_cast <AudioPluginInstance
*> (node
->getProcessor());
95 if (plugin
!= nullptr)
96 ui
->setName (plugin
->getName());
98 return new PluginWindow (ui
, node
, useGenericView
);
104 PluginWindow::~PluginWindow()
106 activePluginWindows
.removeValue (this);
107 clearContentComponent();
110 void PluginWindow::moved()
112 owner
->properties
.set ("uiLastX", getX());
113 owner
->properties
.set ("uiLastY", getY());
116 void PluginWindow::closeButtonPressed()
121 //==============================================================================
122 class PinComponent
: public Component
,
123 public SettableTooltipClient
126 PinComponent (FilterGraph
& graph_
,
127 const uint32 filterID_
, const int index_
, const bool isInput_
)
128 : filterID (filterID_
),
133 const AudioProcessorGraph::Node::Ptr
node (graph
.getNodeForId (filterID_
));
140 tip
= node
->getProcessor()->getInputChannelName (index_
);
142 tip
= node
->getProcessor()->getOutputChannelName (index_
);
146 if (index_
== FilterGraph::midiChannelNumber
)
147 tip
= isInput
? "Midi Input" : "Midi Output";
149 tip
= (isInput
? "Input " : "Output ") + String (index_
+ 1);
158 void paint (Graphics
& g
)
160 const float w
= (float) getWidth();
161 const float h
= (float) getHeight();
164 p
.addEllipse (w
* 0.25f
, h
* 0.25f
, w
* 0.5f
, h
* 0.5f
);
166 p
.addRectangle (w
* 0.4f
, isInput
? (0.5f
* h
) : 0.0f
, w
* 0.2f
, h
* 0.5f
);
168 g
.setColour (index
== FilterGraph::midiChannelNumber
? Colours::red
: Colours::green
);
172 void mouseDown (const MouseEvent
& e
)
174 getGraphPanel()->beginConnectorDrag (isInput
? 0 : filterID
,
176 isInput
? filterID
: 0,
181 void mouseDrag (const MouseEvent
& e
)
183 getGraphPanel()->dragConnector (e
);
186 void mouseUp (const MouseEvent
& e
)
188 getGraphPanel()->endDraggingConnector (e
);
191 const uint32 filterID
;
198 GraphEditorPanel
* getGraphPanel() const noexcept
200 return findParentComponentOfClass ((GraphEditorPanel
*) nullptr);
203 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PinComponent
);
206 //==============================================================================
207 class FilterComponent
: public Component
210 FilterComponent (FilterGraph
& graph_
,
211 const uint32 filterID_
)
213 filterID (filterID_
),
217 font (13.0f
, Font::bold
),
221 shadow
.setShadowProperties (2.5f
, 0.5f
, -1, 0);
222 setComponentEffect (&shadow
);
232 void mouseDown (const MouseEvent
& e
)
234 originalPos
= localPointToGlobal (Point
<int>());
238 if (e
.mods
.isPopupMenu())
241 m
.addItem (1, "Delete this filter");
242 m
.addItem (2, "Disconnect all pins");
244 m
.addItem (3, "Show plugin UI");
245 m
.addItem (4, "Show all parameters");
247 const int r
= m
.show();
251 graph
.removeFilter (filterID
);
256 graph
.disconnectFilter (filterID
);
258 else if (r
== 3 || r
== 4)
260 AudioProcessorGraph::Node::Ptr
f (graph
.getNodeForId (filterID
));
264 PluginWindow
* const w
= PluginWindow::getWindowFor (f
, r
== 4);
273 void mouseDrag (const MouseEvent
& e
)
275 if (! e
.mods
.isPopupMenu())
277 Point
<int> pos (originalPos
+ Point
<int> (e
.getDistanceFromDragStartX(), e
.getDistanceFromDragStartY()));
279 if (getParentComponent() != nullptr)
280 pos
= getParentComponent()->getLocalPoint (nullptr, pos
);
282 graph
.setNodePosition (filterID
,
283 (pos
.getX() + getWidth() / 2) / (double) getParentWidth(),
284 (pos
.getY() + getHeight() / 2) / (double) getParentHeight());
286 getGraphPanel()->updateComponents();
290 void mouseUp (const MouseEvent
& e
)
292 if (e
.mouseWasClicked() && e
.getNumberOfClicks() == 2)
294 const AudioProcessorGraph::Node::Ptr
f (graph
.getNodeForId (filterID
));
298 PluginWindow
* const w
= PluginWindow::getWindowFor (f
, false);
304 else if (! e
.mouseWasClicked())
306 graph
.setChangedFlag (true);
310 bool hitTest (int x
, int y
)
312 for (int i
= getNumChildComponents(); --i
>= 0;)
313 if (getChildComponent(i
)->getBounds().contains (x
, y
))
316 return x
>= 3 && x
< getWidth() - 6 && y
>= pinSize
&& y
< getHeight() - pinSize
;
319 void paint (Graphics
& g
)
321 g
.setColour (Colours::lightgrey
);
324 const int y
= pinSize
;
325 const int w
= getWidth() - x
* 2;
326 const int h
= getHeight() - pinSize
* 2;
328 g
.fillRect (x
, y
, w
, h
);
330 g
.setColour (Colours::black
);
332 g
.drawFittedText (getName(),
333 x
+ 4, y
+ 2, w
- 8, h
- 4,
334 Justification::centred
, 2);
336 g
.setColour (Colours::grey
);
337 g
.drawRect (x
, y
, w
, h
);
342 for (int i
= 0; i
< getNumChildComponents(); ++i
)
344 PinComponent
* const pc
= dynamic_cast <PinComponent
*> (getChildComponent(i
));
348 const int total
= pc
->isInput
? numIns
: numOuts
;
349 const int index
= pc
->index
== FilterGraph::midiChannelNumber
? (total
- 1) : pc
->index
;
351 pc
->setBounds (proportionOfWidth ((1 + index
) / (total
+ 1.0f
)) - pinSize
/ 2,
352 pc
->isInput
? 0 : (getHeight() - pinSize
),
358 void getPinPos (const int index
, const bool isInput
, float& x
, float& y
)
360 for (int i
= 0; i
< getNumChildComponents(); ++i
)
362 PinComponent
* const pc
= dynamic_cast <PinComponent
*> (getChildComponent(i
));
364 if (pc
!= nullptr && pc
->index
== index
&& isInput
== pc
->isInput
)
366 x
= getX() + pc
->getX() + pc
->getWidth() * 0.5f
;
367 y
= getY() + pc
->getY() + pc
->getHeight() * 0.5f
;
375 const AudioProcessorGraph::Node::Ptr
f (graph
.getNodeForId (filterID
));
383 numIns
= f
->getProcessor()->getNumInputChannels();
384 if (f
->getProcessor()->acceptsMidi())
387 numOuts
= f
->getProcessor()->getNumOutputChannels();
388 if (f
->getProcessor()->producesMidi())
394 w
= jmax (w
, (jmax (numIns
, numOuts
) + 1) * 20);
396 const int textWidth
= font
.getStringWidth (f
->getProcessor()->getName());
397 w
= jmax (w
, 16 + jmin (textWidth
, 300));
403 setName (f
->getProcessor()->getName());
407 graph
.getNodePosition (filterID
, x
, y
);
408 setCentreRelative ((float) x
, (float) y
);
411 if (numIns
!= numInputs
|| numOuts
!= numOutputs
)
414 numOutputs
= numOuts
;
419 for (i
= 0; i
< f
->getProcessor()->getNumInputChannels(); ++i
)
420 addAndMakeVisible (new PinComponent (graph
, filterID
, i
, true));
422 if (f
->getProcessor()->acceptsMidi())
423 addAndMakeVisible (new PinComponent (graph
, filterID
, FilterGraph::midiChannelNumber
, true));
425 for (i
= 0; i
< f
->getProcessor()->getNumOutputChannels(); ++i
)
426 addAndMakeVisible (new PinComponent (graph
, filterID
, i
, false));
428 if (f
->getProcessor()->producesMidi())
429 addAndMakeVisible (new PinComponent (graph
, filterID
, FilterGraph::midiChannelNumber
, false));
436 const uint32 filterID
;
437 int numInputs
, numOutputs
;
441 Point
<int> originalPos
;
444 DropShadowEffect shadow
;
446 GraphEditorPanel
* getGraphPanel() const noexcept
448 return findParentComponentOfClass ((GraphEditorPanel
*) nullptr);
451 FilterComponent (const FilterComponent
&);
452 FilterComponent
& operator= (const FilterComponent
&);
455 //==============================================================================
456 class ConnectorComponent
: public Component
,
457 public SettableTooltipClient
460 ConnectorComponent (FilterGraph
& graph_
)
461 : sourceFilterID (0),
463 sourceFilterChannel (0),
464 destFilterChannel (0),
471 setAlwaysOnTop (true);
474 ~ConnectorComponent()
478 void setInput (const uint32 sourceFilterID_
, const int sourceFilterChannel_
)
480 if (sourceFilterID
!= sourceFilterID_
|| sourceFilterChannel
!= sourceFilterChannel_
)
482 sourceFilterID
= sourceFilterID_
;
483 sourceFilterChannel
= sourceFilterChannel_
;
488 void setOutput (const uint32 destFilterID_
, const int destFilterChannel_
)
490 if (destFilterID
!= destFilterID_
|| destFilterChannel
!= destFilterChannel_
)
492 destFilterID
= destFilterID_
;
493 destFilterChannel
= destFilterChannel_
;
498 void dragStart (int x
, int y
)
500 lastInputX
= (float) x
;
501 lastInputY
= (float) y
;
505 void dragEnd (int x
, int y
)
507 lastOutputX
= (float) x
;
508 lastOutputY
= (float) y
;
514 float x1
, y1
, x2
, y2
;
515 getPoints (x1
, y1
, x2
, y2
);
520 || lastOutputY
!= y2
)
528 float x1
, y1
, x2
, y2
;
529 getPoints (x1
, y1
, x2
, y2
);
531 const Rectangle
<int> newBounds ((int) jmin (x1
, x2
) - 4,
532 (int) jmin (y1
, y2
) - 4,
533 (int) fabsf (x1
- x2
) + 8,
534 (int) fabsf (y1
- y2
) + 8);
536 if (newBounds
!= getBounds())
537 setBounds (newBounds
);
544 void getPoints (float& x1
, float& y1
, float& x2
, float& y2
) const
551 GraphEditorPanel
* const hostPanel
= getGraphPanel();
553 if (hostPanel
!= nullptr)
555 FilterComponent
* srcFilterComp
= hostPanel
->getComponentForFilter (sourceFilterID
);
557 if (srcFilterComp
!= nullptr)
558 srcFilterComp
->getPinPos (sourceFilterChannel
, false, x1
, y1
);
560 FilterComponent
* dstFilterComp
= hostPanel
->getComponentForFilter (destFilterID
);
562 if (dstFilterComp
!= nullptr)
563 dstFilterComp
->getPinPos (destFilterChannel
, true, x2
, y2
);
567 void paint (Graphics
& g
)
569 if (sourceFilterChannel
== FilterGraph::midiChannelNumber
570 || destFilterChannel
== FilterGraph::midiChannelNumber
)
572 g
.setColour (Colours::red
);
576 g
.setColour (Colours::green
);
579 g
.fillPath (linePath
);
582 bool hitTest (int x
, int y
)
584 if (hitPath
.contains ((float) x
, (float) y
))
586 double distanceFromStart
, distanceFromEnd
;
587 getDistancesFromEnds (x
, y
, distanceFromStart
, distanceFromEnd
);
589 // avoid clicking the connector when over a pin
590 return distanceFromStart
> 7.0 && distanceFromEnd
> 7.0;
596 void mouseDown (const MouseEvent
&)
601 void mouseDrag (const MouseEvent
& e
)
603 if ((! dragging
) && ! e
.mouseWasClicked())
607 graph
.removeConnection (sourceFilterID
, sourceFilterChannel
, destFilterID
, destFilterChannel
);
609 double distanceFromStart
, distanceFromEnd
;
610 getDistancesFromEnds (e
.x
, e
.y
, distanceFromStart
, distanceFromEnd
);
611 const bool isNearerSource
= (distanceFromStart
< distanceFromEnd
);
613 getGraphPanel()->beginConnectorDrag (isNearerSource
? 0 : sourceFilterID
,
615 isNearerSource
? destFilterID
: 0,
621 getGraphPanel()->dragConnector (e
);
625 void mouseUp (const MouseEvent
& e
)
628 getGraphPanel()->endDraggingConnector (e
);
633 float x1
, y1
, x2
, y2
;
634 getPoints (x1
, y1
, x2
, y2
);
647 linePath
.startNewSubPath (x1
, y1
);
648 linePath
.cubicTo (x1
, y1
+ (y2
- y1
) * 0.33f
,
649 x2
, y1
+ (y2
- y1
) * 0.66f
,
652 PathStrokeType
wideStroke (8.0f
);
653 wideStroke
.createStrokedPath (hitPath
, linePath
);
655 PathStrokeType
stroke (2.5f
);
656 stroke
.createStrokedPath (linePath
, linePath
);
658 const float arrowW
= 5.0f
;
659 const float arrowL
= 4.0f
;
662 arrow
.addTriangle (-arrowL
, arrowW
,
666 arrow
.applyTransform (AffineTransform::identity
667 .rotated (float_Pi
* 0.5f
- (float) atan2 (x2
- x1
, y2
- y1
))
668 .translated ((x1
+ x2
) * 0.5f
,
671 linePath
.addPath (arrow
);
672 linePath
.setUsingNonZeroWinding (true);
675 uint32 sourceFilterID
, destFilterID
;
676 int sourceFilterChannel
, destFilterChannel
;
680 float lastInputX
, lastInputY
, lastOutputX
, lastOutputY
;
681 Path linePath
, hitPath
;
684 GraphEditorPanel
* getGraphPanel() const noexcept
686 return findParentComponentOfClass ((GraphEditorPanel
*) nullptr);
689 void getDistancesFromEnds (int x
, int y
, double& distanceFromStart
, double& distanceFromEnd
) const
691 float x1
, y1
, x2
, y2
;
692 getPoints (x1
, y1
, x2
, y2
);
694 distanceFromStart
= juce_hypot (x
- (x1
- getX()), y
- (y1
- getY()));
695 distanceFromEnd
= juce_hypot (x
- (x2
- getX()), y
- (y2
- getY()));
698 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ConnectorComponent
);
702 //==============================================================================
703 GraphEditorPanel::GraphEditorPanel (FilterGraph
& graph_
)
705 draggingConnector (nullptr)
707 graph
.addChangeListener (this);
711 GraphEditorPanel::~GraphEditorPanel()
713 graph
.removeChangeListener (this);
714 deleteAndZero (draggingConnector
);
718 void GraphEditorPanel::paint (Graphics
& g
)
720 g
.fillAll (Colours::white
);
723 void GraphEditorPanel::mouseDown (const MouseEvent
& e
)
725 if (e
.mods
.isPopupMenu())
729 MainHostWindow
* const mainWindow
= findParentComponentOfClass ((MainHostWindow
*) nullptr);
731 if (mainWindow
!= nullptr)
733 mainWindow
->addPluginsToMenu (m
);
735 const int r
= m
.show();
737 createNewPlugin (mainWindow
->getChosenType (r
), e
.x
, e
.y
);
742 void GraphEditorPanel::createNewPlugin (const PluginDescription
* desc
, int x
, int y
)
744 graph
.addFilter (desc
, x
/ (double) getWidth(), y
/ (double) getHeight());
747 FilterComponent
* GraphEditorPanel::getComponentForFilter (const uint32 filterID
) const
749 for (int i
= getNumChildComponents(); --i
>= 0;)
751 FilterComponent
* const fc
= dynamic_cast <FilterComponent
*> (getChildComponent (i
));
753 if (fc
!= nullptr && fc
->filterID
== filterID
)
760 ConnectorComponent
* GraphEditorPanel::getComponentForConnection (const AudioProcessorGraph::Connection
& conn
) const
762 for (int i
= getNumChildComponents(); --i
>= 0;)
764 ConnectorComponent
* const c
= dynamic_cast <ConnectorComponent
*> (getChildComponent (i
));
767 && c
->sourceFilterID
== conn
.sourceNodeId
768 && c
->destFilterID
== conn
.destNodeId
769 && c
->sourceFilterChannel
== conn
.sourceChannelIndex
770 && c
->destFilterChannel
== conn
.destChannelIndex
)
779 PinComponent
* GraphEditorPanel::findPinAt (const int x
, const int y
) const
781 for (int i
= getNumChildComponents(); --i
>= 0;)
783 FilterComponent
* const fc
= dynamic_cast <FilterComponent
*> (getChildComponent (i
));
787 PinComponent
* const pin
788 = dynamic_cast <PinComponent
*> (fc
->getComponentAt (x
- fc
->getX(),
799 void GraphEditorPanel::resized()
804 void GraphEditorPanel::changeListenerCallback (ChangeBroadcaster
*)
809 void GraphEditorPanel::updateComponents()
812 for (i
= getNumChildComponents(); --i
>= 0;)
814 FilterComponent
* const fc
= dynamic_cast <FilterComponent
*> (getChildComponent (i
));
820 for (i
= getNumChildComponents(); --i
>= 0;)
822 ConnectorComponent
* const cc
= dynamic_cast <ConnectorComponent
*> (getChildComponent (i
));
824 if (cc
!= nullptr && cc
!= draggingConnector
)
826 if (graph
.getConnectionBetween (cc
->sourceFilterID
, cc
->sourceFilterChannel
,
827 cc
->destFilterID
, cc
->destFilterChannel
) == nullptr)
838 for (i
= graph
.getNumFilters(); --i
>= 0;)
840 const AudioProcessorGraph::Node::Ptr
f (graph
.getNode (i
));
842 if (getComponentForFilter (f
->nodeId
) == 0)
844 FilterComponent
* const comp
= new FilterComponent (graph
, f
->nodeId
);
845 addAndMakeVisible (comp
);
850 for (i
= graph
.getNumConnections(); --i
>= 0;)
852 const AudioProcessorGraph::Connection
* const c
= graph
.getConnection (i
);
854 if (getComponentForConnection (*c
) == 0)
856 ConnectorComponent
* const comp
= new ConnectorComponent (graph
);
857 addAndMakeVisible (comp
);
859 comp
->setInput (c
->sourceNodeId
, c
->sourceChannelIndex
);
860 comp
->setOutput (c
->destNodeId
, c
->destChannelIndex
);
865 void GraphEditorPanel::beginConnectorDrag (const uint32 sourceFilterID
, const int sourceFilterChannel
,
866 const uint32 destFilterID
, const int destFilterChannel
,
869 delete draggingConnector
;
870 draggingConnector
= dynamic_cast <ConnectorComponent
*> (e
.originalComponent
);
872 if (draggingConnector
== nullptr)
873 draggingConnector
= new ConnectorComponent (graph
);
875 draggingConnector
->setInput (sourceFilterID
, sourceFilterChannel
);
876 draggingConnector
->setOutput (destFilterID
, destFilterChannel
);
878 addAndMakeVisible (draggingConnector
);
879 draggingConnector
->toFront (false);
884 void GraphEditorPanel::dragConnector (const MouseEvent
& e
)
886 const MouseEvent
e2 (e
.getEventRelativeTo (this));
888 if (draggingConnector
!= nullptr)
890 draggingConnector
->setTooltip (String::empty
);
895 PinComponent
* const pin
= findPinAt (x
, y
);
899 uint32 srcFilter
= draggingConnector
->sourceFilterID
;
900 int srcChannel
= draggingConnector
->sourceFilterChannel
;
901 uint32 dstFilter
= draggingConnector
->destFilterID
;
902 int dstChannel
= draggingConnector
->destFilterChannel
;
904 if (srcFilter
== 0 && ! pin
->isInput
)
906 srcFilter
= pin
->filterID
;
907 srcChannel
= pin
->index
;
909 else if (dstFilter
== 0 && pin
->isInput
)
911 dstFilter
= pin
->filterID
;
912 dstChannel
= pin
->index
;
915 if (graph
.canConnect (srcFilter
, srcChannel
, dstFilter
, dstChannel
))
917 x
= pin
->getParentComponent()->getX() + pin
->getX() + pin
->getWidth() / 2;
918 y
= pin
->getParentComponent()->getY() + pin
->getY() + pin
->getHeight() / 2;
920 draggingConnector
->setTooltip (pin
->getTooltip());
924 if (draggingConnector
->sourceFilterID
== 0)
925 draggingConnector
->dragStart (x
, y
);
927 draggingConnector
->dragEnd (x
, y
);
931 void GraphEditorPanel::endDraggingConnector (const MouseEvent
& e
)
933 if (draggingConnector
== nullptr)
936 draggingConnector
->setTooltip (String::empty
);
938 const MouseEvent
e2 (e
.getEventRelativeTo (this));
940 uint32 srcFilter
= draggingConnector
->sourceFilterID
;
941 int srcChannel
= draggingConnector
->sourceFilterChannel
;
942 uint32 dstFilter
= draggingConnector
->destFilterID
;
943 int dstChannel
= draggingConnector
->destFilterChannel
;
945 deleteAndZero (draggingConnector
);
947 PinComponent
* const pin
= findPinAt (e2
.x
, e2
.y
);
956 srcFilter
= pin
->filterID
;
957 srcChannel
= pin
->index
;
964 dstFilter
= pin
->filterID
;
965 dstChannel
= pin
->index
;
968 graph
.addConnection (srcFilter
, srcChannel
, dstFilter
, dstChannel
);
973 //==============================================================================
974 class TooltipBar
: public Component
,
983 void paint (Graphics
& g
)
985 g
.setFont (getHeight() * 0.7f
, Font::bold
);
986 g
.setColour (Colours::black
);
987 g
.drawFittedText (tip
, 10, 0, getWidth() - 12, getHeight(), Justification::centredLeft
, 1);
992 Component
* const underMouse
= Desktop::getInstance().getMainMouseSource().getComponentUnderMouse();
993 TooltipClient
* const ttc
= dynamic_cast <TooltipClient
*> (underMouse
);
997 if (ttc
!= nullptr && ! (underMouse
->isMouseButtonDown() || underMouse
->isCurrentlyBlockedByAnotherModalComponent()))
998 newTip
= ttc
->getTooltip();
1010 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TooltipBar
);
1013 //==============================================================================
1014 GraphDocumentComponent::GraphDocumentComponent (AudioDeviceManager
* deviceManager_
)
1015 : deviceManager (deviceManager_
)
1017 addAndMakeVisible (graphPanel
= new GraphEditorPanel (graph
));
1019 graphPlayer
.setProcessor (&graph
.getGraph());
1021 keyState
.addListener (&graphPlayer
.getMidiMessageCollector());
1023 addAndMakeVisible (keyboardComp
= new MidiKeyboardComponent (keyState
,
1024 MidiKeyboardComponent::horizontalKeyboard
));
1026 addAndMakeVisible (statusBar
= new TooltipBar());
1028 deviceManager
->addAudioCallback (&graphPlayer
);
1029 deviceManager
->addMidiInputCallback (String::empty
, &graphPlayer
.getMidiMessageCollector());
1031 graphPanel
->updateComponents();
1034 GraphDocumentComponent::~GraphDocumentComponent()
1036 deviceManager
->removeAudioCallback (&graphPlayer
);
1037 deviceManager
->removeMidiInputCallback (String::empty
, &graphPlayer
.getMidiMessageCollector());
1039 deleteAllChildren();
1041 graphPlayer
.setProcessor (nullptr);
1042 keyState
.removeListener (&graphPlayer
.getMidiMessageCollector());
1047 void GraphDocumentComponent::resized()
1049 const int keysHeight
= 60;
1050 const int statusHeight
= 20;
1052 graphPanel
->setBounds (0, 0, getWidth(), getHeight() - keysHeight
);
1053 statusBar
->setBounds (0, getHeight() - keysHeight
- statusHeight
, getWidth(), statusHeight
);
1054 keyboardComp
->setBounds (0, getHeight() - keysHeight
, getWidth(), keysHeight
);
1057 void GraphDocumentComponent::createNewPlugin (const PluginDescription
* desc
, int x
, int y
)
1059 graphPanel
->createNewPlugin (desc
, x
, y
);